package org.com.system.util.dao;

import java.util.List;

import javax.sql.DataSource;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.com.system.util.model.ActionValues;
import org.com.system.util.model.Dao;
import org.com.system.util.model.Page;
import org.com.system.util.sql.DeleteSQLGener;
import org.com.system.util.sql.QuerySQLGener;
import org.com.system.util.sql.SaveSQLGener;
import org.com.system.util.sql.UpdateSQLGener;
import org.com.system.util.utils.CollectionUtils;
import org.com.system.util.utils.ModelUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 * 该类用DBUtils来实现，对于数据库的连接要自己管理
 * @author Gandilong at 2012-9-17下午05:54:51
 * @param <E>
 */
@Repository
@Transactional(propagation=Propagation.SUPPORTS,readOnly=true)
public class JdbcDao<E> implements Dao<E> {
	
	private QueryRunner queryRuner=null;
	private BeanHandler<E> beanHandler=null;
	private BeanListHandler<E> beanListHandler=null;
	
	@Override
	@SuppressWarnings("all")
	@Transactional(propagation=Propagation.REQUIRED,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
	public void save(E entity) {
		try{
		   String sql=SaveSQLGener.saveSQL(entity.getClass());
		   queryRuner.update(sql,ModelUtils.getFieldValues(entity.getClass(),entity));
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	@Override
	@Transactional(propagation=Propagation.REQUIRED,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
	public void save(List<E> entitys) {
		for(E entity:entitys){
			save(entity);
		}
	}
	
	@Override
	@SuppressWarnings("all")
	@Transactional(propagation=Propagation.REQUIRED,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
	public void save(ActionValues<String, Object> values, Class<E> entityClass) {
		try{
		    String sql=SaveSQLGener.saveValuesSQL(values, entityClass);
		    queryRuner.update(sql);
		}catch(Exception e){
			e.printStackTrace();
		}
	}

	@Override
	@Transactional(propagation=Propagation.REQUIRED,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
	public void save(List<ActionValues<String, Object>> values,Class<E> entityClass) {
		for(ActionValues<String, Object> value:values){
			save(value, entityClass);
		}
	}
	
	@Override
	@Transactional(propagation=Propagation.REQUIRED,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
	public void delete(E entity) {
		try{
		    String sql=DeleteSQLGener.deleteSQL(entity, entity.getClass());
		    queryRuner.update(sql);
		}catch(Exception e){
			e.printStackTrace();
		}
	}

	@Override
	@Transactional(propagation=Propagation.REQUIRED,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
	public void delete(String id, Class<E> entityClass) {
		try{
		    String sql=DeleteSQLGener.deleteSQL(id, entityClass);
		    queryRuner.update(sql);
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	@Override
	@Transactional(propagation=Propagation.REQUIRED,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
	public void delete(ActionValues<String, Object> values, Class<E> entityClass) {
		try{
		    String sql=DeleteSQLGener.deleteSQL(values, entityClass);
		    queryRuner.update(sql);
		}catch(Exception e){
			e.printStackTrace();
		}
	}

	@Override
	@Transactional(propagation=Propagation.REQUIRED,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
	public void delete(List<E> entitys) {
		for(E entity:entitys){
			delete(entity);
		}
	}
	
	@Override
	@Transactional(propagation=Propagation.REQUIRED,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
	public void delete(List<String> ids, Class<E> entityClass) {
		for(String id:ids){
			delete(id, entityClass);
		}
	}
	
	@Override
	@Transactional(propagation=Propagation.SUPPORTS,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
	public E get(ActionValues<String, Object> values, Class<E> entityClass) {
		E entity=null;
		try{
		    String sql=QuerySQLGener.getSQL(values, entityClass);
		    entity=queryRuner.query(sql, beanHandler);
		}catch(Exception e){
			e.printStackTrace();
		}
		return entity;
	}

	@Override
	@Transactional(propagation=Propagation.SUPPORTS,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
	public E get(String id, Class<E> entityClass) {
		E entity=null;
		try{
		    String sql=QuerySQLGener.getSQL(id, entityClass);
		    entity=queryRuner.query(sql, beanHandler);
		}catch(Exception e){
			e.printStackTrace();
		}
		return entity;
	}
	
	@Override
	@Transactional(propagation=Propagation.SUPPORTS,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
	public List<E> list(Class<E> entityClass) {
		List<E> list=null;
		try{
		    String sql=QuerySQLGener.listSQL(entityClass);
		    list=queryRuner.query(sql, beanListHandler);
		}catch(Exception e){
			e.printStackTrace();
		}
		return list;
	}


	@Override
	@Transactional(propagation=Propagation.SUPPORTS,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
	public List<E> list(Class<E> entityClass, Page page) {
		List<E> list=null;
		try{
		    String sql=QuerySQLGener.listSQL(entityClass,page);
		    list=queryRuner.query(sql, beanListHandler);
		}catch(Exception e){
			e.printStackTrace();
		}
		return list;
	}
	
	@Override
	@Transactional(propagation=Propagation.SUPPORTS,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
	public List<E> list(ActionValues<String, Object> values,Class<E> entityClass) {
		List<E> list=null;
		try{
		    String sql=QuerySQLGener.listSQL(values,entityClass);
		    list=queryRuner.query(sql, beanListHandler);
		}catch(Exception e){
			e.printStackTrace();
		}
		return list;
	}

	@Override
	@Transactional(propagation=Propagation.SUPPORTS,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
	public List<E> list(ActionValues<String, Object> values,Class<E> entityClass, Page page) {
		List<E> list=null;
		try{
		    String sql=QuerySQLGener.listSQL(values,entityClass,page);
		    list=queryRuner.query(sql, beanListHandler);
		}catch(Exception e){
			e.printStackTrace();
		}
		return list;
	}

	@Override
	@SuppressWarnings("all")
	@Transactional(propagation=Propagation.REQUIRED,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
	public void update(E entity) {
		try{
		    String sql=UpdateSQLGener.updateSQL(entity.getClass());
		    String[] values=ModelUtils.getFieldValues(entity.getClass(),entity);
		    CollectionUtils.moveFirstToLast(values);
		    for(int i=0;i<values.length;i++){
		    	System.out.println(values[i]);
		    }
		    queryRuner.update(sql, values);
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	@Override
	@Transactional(propagation=Propagation.REQUIRED,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
	public void update(List<E> entitys) {
		for(E entity:entitys){
			update(entity);
		}
	}
	
	@Override
	@Transactional(propagation=Propagation.REQUIRED,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
	public void update(ActionValues<String, Object> values, Class<E> entityClass) {
		try{
		    String sql=UpdateSQLGener.updateValuesSQL(values,entityClass);
		    queryRuner.update(sql);
		}catch(Exception e){
			e.printStackTrace();
		}
	}

	@Override
	@Transactional(propagation=Propagation.REQUIRED,rollbackFor={RuntimeException.class, Exception.class},readOnly=false)
	public void update(List<ActionValues<String, Object>> values,Class<E> entityClass) {
		for(ActionValues<String,Object> value:values){
			update(value, entityClass);
		}
	}

	@Autowired
	public void setQueryRuner(@Qualifier("dataSource_system")DataSource dataSource) {
		this.queryRuner = new QueryRunner(dataSource,false);
	}

	public void setBeanHandler(BeanHandler<E> beanHandler) {
		this.beanHandler = beanHandler;
	}

	public void setBeanListHandler(BeanListHandler<E> beanListHandler) {
		this.beanListHandler = beanListHandler;
	}

}
